#ifndef __AMR_VAD_H__
#define __AMR_VAD_H__

#if (CONFIG_APP_ADC_VAD == 1) || (CONFIG_APP_DAC_VAD == 1)
#include "basic_op.h"
#if (CONFIG_APP_MSBC_RESAMPLE == 1)
#define VAD_TOTAL_LEN 240
#define VAD_FRAME_LEN 120   /* Length (samples) of the input frame */
#define VAD_SUBFRAME_LEN 60 /* sbc frame length,an half of FRMAE_LEN */
#else
#define VAD_TOTAL_LEN 480
#define VAD_FRAME_LEN 240    /* Length (samples) of the input frame */
#define VAD_SUBFRAME_LEN 120 /* sbc frame length,an half of FRMAE_LEN */
#endif
#define COMPLEN 9        /* Number of sub-bands used by VAD              */
#define INV_COMPLEN 3641 /* 1.0/COMPLEN*2^15                             */
#define LOOKAHEAD 40     /* length of the lookahead used by speech coder */

#define UNITY 512  /* Scaling used with SNR calculation            */
#define UNIRSHFT 6 /* = log2(MAX_16/UNITY)                         */

#define TONE_THR (Word16)(0.65 * MAX_16) /* Threshold for tone detection   */

/* Constants for background spectrum update */
#define ALPHA_UP1 (Word16)((1.0 - 0.95) * MAX_16)    /* Normal update, upwards:   */
#define ALPHA_DOWN1 (Word16)((1.0 - 0.936) * MAX_16) /* Normal update, downwards  */
#define ALPHA_UP2 (Word16)((1.0 - 0.985) * MAX_16)   /* Forced update, upwards    */
#define ALPHA_DOWN2 (Word16)((1.0 - 0.943) * MAX_16) /* Forced update, downwards  */
#define ALPHA3 (Word16)((1.0 - 0.95) * MAX_16)       /* Update downwards          */
#define ALPHA4 (Word16)((1.0 - 0.9) * MAX_16)        /* For stationary estimation */
#define ALPHA5 (Word16)((1.0 - 0.5) * MAX_16)        /* For stationary estimation */

/* Constants for VAD threshold */
#define VAD_THR_HIGH 1260 /* Highest threshold                 */
#define VAD_THR_LOW 720   /* Lowest threshold                  */
#define VAD_P1 0          /* Noise level for highest threshold */
#define VAD_P2 6300       /* Noise level for lowest threshold  */
#define VAD_SLOPE (Word16)(MAX_16 * (float)(VAD_THR_LOW - VAD_THR_HIGH) / (float)(VAD_P2 - VAD_P1))

/* Parameters for background spectrum recovery function */
#define STAT_COUNT 20        /* threshold of stationary detection counter         */
#define STAT_COUNT_BY_2 10   /* threshold of stationary detection counter         */
#define CAD_MIN_STAT_COUNT 5 /* threshold of stationary detection counter         */

#define STAT_THR_LEVEL 184 /* Threshold level for stationarity detection        */
#define STAT_THR 1000      /* Threshold for stationarity detection              */

/* Limits for background noise estimate */
#define NOISE_MIN 40    /* minimum */
#define NOISE_MAX 16000 /* maximum */
#define NOISE_INIT 150  /* initial */

/* Constants for VAD hangover addition */
#define HANG_NOISE_THR 100
#define BURST_LEN_HIGH_NOISE 4
#define HANG_LEN_HIGH_NOISE 7
#define BURST_LEN_LOW_NOISE 5
#define HANG_LEN_LOW_NOISE 4

/* Thresholds for signal power */
#define VAD_POW_LOW (Word32)15000    /* If input power is lower,                    */
                                     /*     VAD is set to 0                         */
#define POW_PITCH_THR (Word32)343040 /* If input power is lower, pitch              */
                                     /*     detection is ignored                    */

#define POW_COMPLEX_THR (Word32)15000 /* If input power is lower, complex            */
                                      /* flags  value for previous frame  is un-set  */

/* Constants for the filter bank */
#define LEVEL_SHIFT 0  /* scaling                                  */
#define COEFF3 13363   /* coefficient for the 3rd order filter     */
#define COEFF5_1 21955 /* 1st coefficient the for 5th order filter */
#define COEFF5_2 6390  /* 2nd coefficient the for 5th order filter */

/* Constants for pitch detection */
#define LTHRESH 4
#define NTHRESH 4

/* Constants for complex signal VAD  */
#define CVAD_THRESH_ADAPT_HIGH (Word16)(0.6 * MAX_16) /* threshold for adapt stopping high    */
#define CVAD_THRESH_ADAPT_LOW (Word16)(0.5 * MAX_16)  /* threshold for adapt stopping low     */
#define CVAD_THRESH_IN_NOISE (Word16)(0.65 * MAX_16)  /* threshold going into speech on \
                                                         a short term basis                   */

#define CVAD_THRESH_HANG (Word16)(0.70 * MAX_16) /* threshold                            */
#define CVAD_HANG_LIMIT (Word16)(100)            /* 2 second estimation time             */
#define CVAD_HANG_LENGTH (Word16)(250)           /* 5 second hangover                    */

#define CVAD_LOWPOW_RESET (Word16)(0.40 * MAX_16) /* init in low power segment            */
#define CVAD_MIN_CORR (Word16)(0.40 * MAX_16)     /* lowest adaptation value              */

#define CVAD_BURST 20                                          /* speech burst length for speech reset */
#define CVAD_ADAPT_SLOW (Word16)((1.0 - 0.98) * MAX_16)        /* threshold for slow adaption */
#define CVAD_ADAPT_FAST (Word16)((1.0 - 0.92) * MAX_16)        /* threshold for fast adaption */
#define CVAD_ADAPT_REALLY_FAST (Word16)((1.0 - 0.80) * MAX_16) /* threshold for really fast \
                                                                  adaption                    */

/* state variable */
typedef struct
{

   Word16 bckr_est[COMPLEN];  /* background noise estimate                */
   Word16 ave_level[COMPLEN]; /* averaged input components for stationary */
                              /*    estimation                            */
   Word16 old_level[COMPLEN]; /* input levels of the previous frame       */
   Word16 sub_level[COMPLEN]; /* input levels calculated at the end of
                                      a frame (lookahead)                   */
   Word16 a_data5[3][2];      /* memory for the filter bank               */
   Word16 a_data3[5];         /* memory for the filter bank               */

   Word16 burst_count; /* counts length of a speech burst          */
   Word16 hang_count;  /* hangover counter                         */
   Word16 stat_count;  /* stationary counter                       */

   /* Note that each of the following three variables (vadreg, pitch and tone)
      holds 15 flags. Each flag reserves 1 bit of the variable. The newest
      flag is in the bit 15 (assuming that LSB is bit 1 and MSB is bit 16). */
   Word16 vadreg;       /* flags for intermediate VAD decisions     */
   Word16 pitch;        /* flags for pitch detection                */
   Word16 tone;         /* flags for tone detection                 */
   Word16 complex_high; /* flags for complex detection              */
   Word16 complex_low;  /* flags for complex detection              */

   Word16 oldlag_count, oldlag; /* variables for pitch detection            */

   Word16 complex_hang_count; /* complex hangover counter, used by VAD    */
   Word16 complex_hang_timer; /* hangover initiator, used by CAD          */

   Word16 best_corr_hp; /* FIP filtered value Q15                   */

   Word16 speech_vad_decision; /* final decision                           */
   Word16 complex_warning;     /* complex background warning               */

   Word16 sp_burst_count; /* counts length of a speech burst incl
                                   HO addition                              */
   Word16 corr_hp_fast;   /* filtered value                           */
   Word16 mute_flag;
   Word16 mem_speech[VAD_TOTAL_LEN];
} vadState1;

/*
********************************************************************************
*                         DECLARATION OF PROTOTYPES
********************************************************************************
*/
int vad1_init(vadState1 **st);
/* initialize one instance of the pre processing state.
   Stores pointer to filter status struct in *st. This pointer has to
   be passed to vad in each call.
   returns 0 on success
 */

int vad1_reset(vadState1 *st);
/* reset of pre processing state (i.e. set state memory to zero)
   returns 0 on success
 */

void vad1_exit(vadState1 **st);
/* de-initialize pre processing state (i.e. free status struct)
   stores NULL in *st
 */

void vad_complex_detection_update(vadState1 *st,      /* i/o : State struct     */
                                  Word16 best_corr_hp /* i   : best Corr Q15    */
);

void vad_tone_detection(vadState1 *st, /* i/o : State struct            */
                        Word32 t0,     /* i   : autocorrelation maxima  */
                        Word32 t1      /* i   : energy                  */
);

void vad_tone_detection_update(
    vadState1 *st,           /* i/o : State struct              */
    Word16 one_lag_per_frame /* i   : 1 if one open-loop lag is
                                              calculated per each frame,
                                              otherwise 0                     */
);

void vad_pitch_detection(vadState1 *st, /* i/o : State struct                  */
                         Word16 lags[]  /* i   : speech encoder open loop lags */
);

Word16 vad1(vadState1 *st,  /* i/o : State struct                      */
            Word16 in_buf[] /* i   : samples of the input frame 
                                inbuf[159] is the very last sample,
                                incl lookahead                          */
);
#endif
#endif
